package com.evan.review.classloader;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

import com.evan.review.R;

import java.io.File;

import dalvik.system.DexClassLoader;
import dalvik.system.PathClassLoader;

/**
 * 类加载器机制演示Activity
 * <p>
 * 特点：
 * 1. 展示Android中的类加载器层次结构
 * 2. 演示类加载的双亲委派机制
 * 3. 对比Class.forName与ClassLoader的区别
 * 4. 演示自定义类加载器的使用
 */
public class ClassLoaderActivity extends AppCompatActivity {

    private static final String TAG = "ClassLoaderActivity";
    private TextView tvInfo;
    private TextView tvResult;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_classloader);

        initViews();
        displayClassLoaderHierarchy();
    }

    private void initViews() {
        tvInfo = findViewById(R.id.tv_info);
        tvResult = findViewById(R.id.tv_result);

        // 显示类加载器层次结构按钮
        Button btnShowHierarchy = findViewById(R.id.btn_show_hierarchy);
        btnShowHierarchy.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                displayClassLoaderHierarchy();
            }
        });

        // 演示双亲委派机制按钮
        Button btnParentDelegation = findViewById(R.id.btn_parent_delegation);
        btnParentDelegation.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                demonstrateParentDelegation();
            }
        });

        // 对比Class.forName和ClassLoader.loadClass按钮
        Button btnCompareLoading = findViewById(R.id.btn_compare_loading);
        btnCompareLoading.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                compareClassLoading();
            }
        });

        // 演示自定义类加载器按钮
        Button btnCustomLoader = findViewById(R.id.btn_custom_loader);
        btnCustomLoader.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                demonstrateCustomClassLoader();
            }
        });

        // 演示反射机制按钮
        Button btnReflection = findViewById(R.id.btn_reflection);
        btnReflection.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                demonstrateReflection();
            }
        });

        // 启动详细演示页面按钮
        Button btnClassLoadingDetail = findViewById(R.id.btn_class_loading_detail);
        btnClassLoadingDetail.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(ClassLoaderActivity.this, ClassLoadingDetailActivity.class));
            }
        });
    }

    /**
     * 显示当前应用的类加载器层次结构
     */
    private void displayClassLoaderHierarchy() {
        StringBuilder result = new StringBuilder();

        // 获取当前类的ClassLoader
        ClassLoader currentClassLoader = getClassLoader();

        result.append("【类加载器层次结构】\n\n");

        int level = 1;
        ClassLoader cl = currentClassLoader;
        while (cl != null) {
            result.append(level).append(". ").append(cl.getClass().getName()).append("\n   ")
                    .append("HashCode: ").append(cl.hashCode()).append("\n");

            // 获取父加载器
            cl = cl.getParent();
            level++;
        }

        // 显示BootClassLoader信息
        result.append(level).append(". BootClassLoader (Native C++实现)\n   ")
                .append("这是最顶层的类加载器，由C++实现，Java中表现为null\n\n");

        result.append("Android类加载器特点：\n");
        result.append("1. PathClassLoader: 加载已安装应用的dex文件\n");
        result.append("2. DexClassLoader: 可加载jar/apk/dex文件，支持动态加载\n");
        result.append("3. BootClassLoader: 加载Android核心类库\n\n");

        tvResult.setText(result.toString());

        updateInfoPanel();
    }

    /**
     * 演示双亲委派机制
     */
    private void demonstrateParentDelegation() {
        StringBuilder result = new StringBuilder();
        result.append("【双亲委派机制演示】\n\n");

        try {
            // 获取当前应用的ClassLoader
            ClassLoader myLoader = getClassLoader();

            // 尝试加载不同包的类，观察使用的ClassLoader
            Class<?> stringClass = myLoader.loadClass("java.lang.String");
            Class<?> activityClass = myLoader.loadClass("android.app.Activity");
            Class<?> myClass = myLoader.loadClass("com.evan.review.classloader.ClassLoaderActivity");

            result.append("1. java.lang.String类由谁加载?\n   ")
                    .append(stringClass.getClassLoader() == null ? "BootClassLoader (显示为null)" : stringClass.getClassLoader())
                    .append("\n\n");

            result.append("2. android.app.Activity类由谁加载?\n   ")
                    .append(activityClass.getClassLoader().getClass().getName())
                    .append("\n   HashCode: ")
                    .append(activityClass.getClassLoader().hashCode())
                    .append("\n\n");

            result.append("3. 当前应用自定义类由谁加载?\n   ")
                    .append(myClass.getClassLoader().getClass().getName())
                    .append("\n   HashCode: ")
                    .append(myClass.getClassLoader().hashCode())
                    .append("\n\n");

            result.append("双亲委派机制工作原理：\n");
            result.append("1. 收到类加载请求时，先委托父加载器加载\n");
            result.append("2. 父加载器无法加载时，子加载器才尝试自己加载\n");
            result.append("3. 确保核心类库的安全性，防止用户自定义的类替代核心类\n\n");

            result.append("面试要点：\n");
            result.append("- 能正确描述Android中的类加载器层次结构\n");
            result.append("- 理解为什么String类加载器是null (BootClassLoader)\n");
            result.append("- 能解释双亲委派模型防止安全漏洞的原理\n");
        } catch (Exception e) {
            result.append("加载类时出错: ").append(e.getMessage());
            Log.e(TAG, "加载类时出错", e);
        }

        tvResult.setText(result.toString());
        updateInfoPanel();
    }

    /**
     * 对比Class.forName与ClassLoader.loadClass的区别
     */
    private void compareClassLoading() {
        StringBuilder result = new StringBuilder();
        result.append("【Class.forName与ClassLoader.loadClass对比】\n\n");

        try {
            long startTime, endTime;

            // 测试Class.forName (默认会初始化)
            startTime = System.currentTimeMillis();
            Class<?> cls1 = Class.forName("com.evan.review.classloader.TestInitClass");
            endTime = System.currentTimeMillis();
            result.append("1. Class.forName加载并初始化:\n");
            result.append("   时间: ").append(endTime - startTime).append("ms\n");
            result.append("   静态代码块是否执行: 是 (查看日志)\n\n");

            // 测试ClassLoader.loadClass (默认不初始化)
            startTime = System.currentTimeMillis();
            Class<?> cls2 = getClassLoader().loadClass("com.evan.review.classloader.TestInitClass");
            endTime = System.currentTimeMillis();
            result.append("2. ClassLoader.loadClass仅加载:\n");
            result.append("   时间: ").append(endTime - startTime).append("ms\n");
            result.append("   静态代码块是否执行: 否 (没有日志输出)\n\n");

            // 主动初始化cls2
            startTime = System.currentTimeMillis();
            Object obj = cls2.newInstance();
            endTime = System.currentTimeMillis();
            result.append("3. 主动初始化cls2后:\n");
            result.append("   时间: ").append(endTime - startTime).append("ms\n");
            result.append("   静态代码块是否再次执行: 否 (类只会初始化一次)\n\n");

            result.append("Class.forName与ClassLoader.loadClass区别:\n");
            result.append("1. Class.forName会默认执行类的初始化，执行静态块和静态变量赋值\n");
            result.append("2. ClassLoader.loadClass默认不初始化类\n");
            result.append("3. Class.forName有三参数版本可控制是否初始化\n\n");

            result.append("面试要点:\n");
            result.append("- 加载JDBC驱动常用Class.forName而非ClassLoader.loadClass\n");
            result.append("- 能解释类加载过程: 加载 → 连接(验证、准备、解析) → 初始化\n");
            result.append("- forName常用于反射构建实例，loadClass常用框架底层实现\n");
        } catch (Exception e) {
            result.append("对比加载方式时出错: ").append(e.getMessage());
            Log.e(TAG, "对比加载方式时出错", e);
        }

        tvResult.setText(result.toString());
        updateInfoPanel();
    }

    /**
     * 演示自定义类加载器
     */
    private void demonstrateCustomClassLoader() {
        StringBuilder result = new StringBuilder();
        result.append("【自定义类加载器演示】\n\n");

        try {
            // 获取应用默认的类加载器
            ClassLoader defaultLoader = getClassLoader();
            result.append("1. 应用默认类加载器:\n   ")
                    .append(defaultLoader.getClass().getName())
                    .append("\n\n");

            // PathClassLoader示例 (Android默认使用的类加载器)
            PathClassLoader pathLoader = new PathClassLoader(
                    getPackageCodePath(),
                    defaultLoader.getParent()
            );

            // 使用PathClassLoader加载当前应用内的类
            Class<?> activityClass = pathLoader.loadClass("com.evan.review.classloader.ClassLoaderActivity");
            result.append("2. 使用PathClassLoader加载应用内类:\n   ")
                    .append("加载成功: ").append(activityClass != null)
                    .append("\n   是否与默认加载的相同: ")
                    .append(activityClass == ClassLoaderActivity.class)
                    .append("\n\n");

            // DexClassLoader示例 (动态加载外部dex)
            File cacheDir = getCodeCacheDir();
            DexClassLoader dexLoader = new DexClassLoader(
                    getPackageCodePath(),
                    cacheDir.getAbsolutePath(),
                    null,
                    defaultLoader.getParent()
            );

            // 使用DexClassLoader加载当前应用内的类
            Class<?> activityClass2 = dexLoader.loadClass("com.evan.review.classloader.ClassLoaderActivity");
            result.append("3. 使用DexClassLoader加载应用内类:\n   ")
                    .append("加载成功: ").append(activityClass2 != null)
                    .append("\n   是否与默认加载的相同: ")
                    .append(activityClass2 == ClassLoaderActivity.class)
                    .append("\n\n");

            result.append("Android中常用类加载器：\n");
            result.append("1. PathClassLoader: 只能加载已安装应用的dex文件，是Android默认类加载器\n");
            result.append("2. DexClassLoader: 功能更强，可以加载jar/apk/dex文件，支持动态加载\n");
            result.append("3. 自Android 8.0起，两者实现已合并，仅保留API兼容性\n\n");

            result.append("面试要点：\n");
            result.append("- 热修复原理：通过自定义ClassLoader加载补丁dex并优先加载\n");
            result.append("- 插件化原理：使用DexClassLoader动态加载外部dex/apk\n");
            result.append("- 理解类加载的缓存机制，同一个ClassLoader不会重复加载同一个类\n");
        } catch (Exception e) {
            result.append("演示类加载器时出错: ").append(e.getMessage());
            Log.e(TAG, "演示类加载器时出错", e);
        }

        tvResult.setText(result.toString());
        updateInfoPanel();
    }

    /**
     * 演示Java反射机制的基本使用
     */
    private void demonstrateReflection() {
        StringBuilder result = new StringBuilder();
        result.append("【Java反射机制演示】\n\n");
        
        try {
            // 1. 获取Class对象的方式
            result.append("1. 获取Class对象的三种方式:\n");
            
            // 方式一：Class.forName()
            Class<?> cls1 = Class.forName("com.evan.review.classloader.TestInitClass");
            result.append("   方式一 Class.forName(): ").append(cls1.getName()).append("\n");
            
            // 方式二：类名.class
            Class<?> cls2 = TestInitClass.class;
            result.append("   方式二 类名.class: ").append(cls2.getName()).append("\n");
            
            // 方式三：对象.getClass()
            TestInitClass obj = new TestInitClass();
            Class<?> cls3 = obj.getClass();
            result.append("   方式三 对象.getClass(): ").append(cls3.getName()).append("\n\n");
            
            // 2. 获取类的属性
            result.append("2. 获取类的成员变量:\n");
            
            // 获取公有字段
            result.append("   公有字段: ");
            java.lang.reflect.Field[] publicFields = cls1.getFields();
            for (java.lang.reflect.Field field : publicFields) {
                result.append(field.getName()).append(", ");
            }
            result.append("\n");
            
            // 获取所有字段（包括私有）
            result.append("   所有字段(含私有): ");
            java.lang.reflect.Field[] allFields = cls1.getDeclaredFields();
            for (java.lang.reflect.Field field : allFields) {
                result.append(field.getName()).append(", ");
            }
            result.append("\n\n");
            
            // 3. 获取并调用方法
            result.append("3. 反射获取并调用方法:\n");
            
            // 获取实例方法并调用
            java.lang.reflect.Method instanceMethod = cls1.getMethod("instanceMethod");
            result.append("   方法: ").append(instanceMethod.getName()).append("\n");
            result.append("   调用方法: ");
            instanceMethod.invoke(obj);
            result.append("请查看Logcat日志输出\n\n");
            
            // 4. 访问私有成员
            result.append("4. 访问私有成员:\n");
            try {
                // 获取私有方法
                java.lang.reflect.Method privateMethod = cls1.getDeclaredMethod("staticMethod");
                privateMethod.setAccessible(true); // 破除访问限制
                result.append("   调用私有静态方法: ");
                Object returnValue = privateMethod.invoke(null);
                result.append("返回值: ").append(returnValue).append("\n\n");
            } catch (Exception e) {
                result.append("   访问私有方法出错: ").append(e.getMessage()).append("\n\n");
            }
            
            // 5. 反射创建对象
            result.append("5. 通过反射创建对象:\n");
            java.lang.reflect.Constructor<?> constructor = cls1.getConstructor();
            Object newInstance = constructor.newInstance();
            result.append("   创建新实例: ").append(newInstance).append("\n");
            result.append("   新实例类型: ").append(newInstance.getClass().getName()).append("\n\n");
            
            result.append("反射机制主要应用场景:\n");
            result.append("1. 框架开发: Spring依赖注入、ORM框架\n");
            result.append("2. 注解处理: 运行时获取注解信息\n");
            result.append("3. 动态代理: AOP面向切面编程\n");
            result.append("4. 热修复和插件化: 动态加载新类\n");
            result.append("5. 获取泛型信息: 绕过类型擦除限制\n\n");
            
            result.append("面试要点:\n");
            result.append("- 理解反射的性能开销(比直接调用慢约100-200倍)\n");
            result.append("- 掌握反射API: getMethod/getField/setAccessible等\n");
            result.append("- 知道Android P及以上对非SDK接口反射的限制\n");
            result.append("- 理解反射与注解、泛型的结合使用\n");
        } catch (Exception e) {
            result.append("反射演示出错: ").append(e.getMessage());
            Log.e(TAG, "反射演示出错", e);
        }
        
        tvResult.setText(result.toString());
        updateInfoPanel();
    }

    /**
     * 更新信息面板内容
     */
    private void updateInfoPanel() {
        StringBuilder info = new StringBuilder();
        
        info.append("【类加载器与反射知识点】\n\n");
        
        info.append("类加载器原理:\n");
        info.append("1. 负责将类的字节码加载到JVM中并完成类的创建\n");
        info.append("2. Android中使用PathClassLoader和DexClassLoader\n");
        info.append("3. 遵循双亲委派模型确保类唯一性和安全性\n\n");
        
        info.append("反射机制原理:\n");
        info.append("1. 在运行时检查、访问和修改类的成员\n");
        info.append("2. 支持调用私有方法和访问私有字段\n");
        info.append("3. 是很多框架和动态特性的基础\n\n");
        
        info.append("面试高频知识点:\n");
        info.append("1. 类加载器层次结构及加载顺序\n");
        info.append("2. Class.forName与ClassLoader.loadClass区别\n");
        info.append("3. 双亲委派机制的实现原理和优点\n");
        info.append("4. 反射性能开销及优化方案\n");
        info.append("5. 热修复和插件化中的类加载与反射应用\n\n");
        
        info.append("操作提示:\n");
        info.append("点击各按钮查看不同知识点的演示和分析\n");
        info.append("查看Logcat日志可获取更多运行时信息\n");
        info.append("标签过滤: ClassLoaderActivity和TestInitClass\n");
        info.append("更多详细资料请见ClassLoaderDoc.java文件\n");
        
        tvInfo.setText(info.toString());
    }

    /**
     * 获取当前应用的ClassLoader
     */
    public ClassLoader getClassLoader() {
        return this.getClass().getClassLoader() != null ? this.getClass().getClassLoader() : ClassLoader.getSystemClassLoader();
    }
} 